package top.hidoctor.auscultation.utils;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.SystemClock;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;

import com.tang.util.BigDecimalUtil;
import com.tang.util.GsonUtil;
import com.tang.util.HexUtil;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import top.hidoctor.auscultation.bean.BlueFileBean;

public class BlueToothDataUtils {
    /**
     * 16进制字符串转十进制int
     *
     * @param HexString
     * @return
     */
    public static int HexStringToInt(String HexString) {
        int inJTFingerLockAddress = Integer.valueOf(HexString, 16);
        return inJTFingerLockAddress;
    }

    /**
     * 16进制字符串转十进制int
     *
     * @return
     */
    public static List<Integer> HexArray2Int(List<String> data) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < data.size(); i++) {
            list.add(HexStringToInt(data.get(i)));
        }
        return list;
    }

    /**
     * 16进制int转十进制int
     *
     * @return
     */
    public static List<String> HexArray2Int2(List<Integer> data) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < data.size(); i++) {
            list.add(Integer.toHexString(data.get(i)));
        }
        return list;
    }

    /**
     * 将高低位数据归一化
     *
     * @param
     * @return {number}
     */
    public static Float getComplement(String data) {
        int LInt = HexStringToInt(data.substring(0, 2));
        int RInt = HexStringToInt(data.substring(2, 4));
        double res = 0;
        if (RInt >= 128) {
            RInt = RInt - 128;
            res = RInt * 256 + LInt;
            res = res - 32767;
        } else {
            res = RInt * 256 + LInt;
        }
        res = BigDecimalUtil.div(res, 32768) * 10.0;
        if (res < -0.55) {
            res = -0.55;
        } else if (res > 0.55) {
            res = 0.55;
        }
        return (float) res;
    }

    // 心音参数
    private static int ORDER_HT = 4;
    private static Double[] PARA_NUM_HT = new Double[]{1.0, -3.69905687174103, 5.14920434916213, -3.19928074902097, 0.749180967484160};
    private static Double[] PARA_DEN_HT = new Double[]{0.00908576605455529, 0.0, -0.0181715321091106, 0.0, 0.00908576605455529};

    // 心音滤波数组
    private static Double[] filter_x_HT = init(ORDER_HT);
    private static Double[] filter_y_HT = init(ORDER_HT);

    private static float filter_HT(double dataIn) {
        double dataOut = 0.0;

        for (int i = 0; i < ORDER_HT; i++) {
            dataOut += PARA_DEN_HT[i + 1] * filter_x_HT[i] - PARA_NUM_HT[i + 1] * filter_y_HT[i];
        }

        dataOut += PARA_DEN_HT[0] * dataIn;
        for (int j = ORDER_HT - 1; j > 0; j--) {
            filter_x_HT[j] = filter_x_HT[j - 1];
            filter_y_HT[j] = filter_y_HT[j - 1];
        }

        filter_x_HT[0] = dataIn;
        filter_y_HT[0] = dataOut;
        return (float) dataOut;
    }

    private static Double[] init(int ORDER) {
        Double[] list = new Double[ORDER];
        for (int i = 0; i < ORDER; i++) {
            list[i] = 0.0;
        }
        return list;
    }


    /**
     * @param {*}
     * @return {*}
     * @description: 滤波数据转换
     */
    public static String transformData(String data) {
        StringBuffer str = new StringBuffer("");
        List<Integer> dataOut = new ArrayList<>();
        Integer[] resultDataAry = {};

        for (int i = 0; i < data.length(); i += 4) {
            Float childValue = getComplement(data.substring(i, i + 4)); // 归一化
            int filterValue = getComplementCode(Math.round(filter_HT(childValue) * 32768)); // 滤波返回的 flaot
            dataOut.add(filterValue % 256);
            dataOut.add(filterValue / 256);
        }

        for (int i = 0; i < dataOut.size(); i++) {
            str.append(complete16String(dataOut.get(i)));
        }

        Log.i("TAG", "transformData: " + str.toString());
        return str.toString();
    }

    private static int getComplementCode(int data) {
        if (data < 0) {
            data = Integer.valueOf(65535 + data);
        } else if (data == 0) {
            return 0;
        }
        return data;
    }

    private static String complete16String(int num) {
        return num > 15 ? Integer.toHexString(num) : "0" + Integer.toHexString(num);
    }


    public static BlueFileBean dataRestructure(List<String> dataInput) {
        if (dataInput.get(0).equals("a6") || dataInput.get(0).equals("a5") || dataInput.get(0).equals("b4") || dataInput.get(0).equals("b5") || dataInput.get(0).equals("b6")) {
            int crcCounting = 0;
            //计算效验值
            for (int i = 0; i < dataInput.size() - 2; i++) {
                crcCounting += HexStringToInt(dataInput.get(i));
            }
//            标记信息
            List<String> signInfo = dataInput.subList(0, 6);
            BlueFileBean resultInfo = new BlueFileBean();
            //cmd命令类型
            resultInfo.setCmd(signInfo.get(0));
            //LEn转换
            resultInfo.setIntLen(HexStringToInt(signInfo.get(1)));
            //包序号转换
            resultInfo.setIntSign(HexArray2Int(signInfo.subList(2, signInfo.size())));
            //数据包
            resultInfo.setData(dataInput.subList(6, dataInput.size() - 2));
            // 转换效验和
            resultInfo.setIntCrc(HexStringToInt(dataInput.get(dataInput.size() - 2)));
            //结束符 0  无后续  1 有后续
            resultInfo.setEndSign(dataInput.get(dataInput.size() - 1));

            if (resultInfo.getIntCrc() != crcCounting % 256) {
                Log.e("TAG", "dataRestructure: 本条数据不通过");
            }
            Log.e("TAG", "dataRestructure: " + GsonUtil.toJsonStr(resultInfo));
            return resultInfo;
        }
        return null;
    }

    public static List<String> getFolderData(List<String> data) {
        StringBuffer pathString = new StringBuffer("");
        List<String> fileList = new ArrayList<>();
        String[] pathArray;

        for (int i = 0; i < data.size(); i++) {
            if (data.get(i).equals("00")) {
                pathString.append("/");
            }
            Pattern pattern = Pattern.compile("[0-9a-zA-Z_.]{1,2}");
            boolean matches = pattern.matcher(fromCharCode(HexStringToInt(data.get(i)))).matches();
            if (matches) {
                pathString.append(fromCharCode(HexStringToInt(data.get(i))));
            }
        }

        pathArray = pathString.toString().split("/");

        for (int i = 0; i < pathArray.length; i++) {
            if (!TextUtils.isEmpty(pathArray[i])) {
                fileList.add(pathArray[i]);
            }
        }
        Log.e("TAG", "getFolderData: " + fileList.toString());
        return fileList;
    }

    public static String fromCharCode(int i) {
        String strValue = "" + (char) i;
        return strValue;
    }

    private static List<Integer> filePathTranslate(String pathStr) {
        List<Integer> hexAry = new ArrayList<>();
        for (int i = 0; i < pathStr.length(); i++) {
            char c = pathStr.charAt(i);
            Integer integer = Integer.valueOf(c);
            hexAry.add(integer);
        }
        return hexAry;
    }

    public static String handleClickToTranslate(String filename, String cmdType) {
        List<Integer> asciiVal = filePathTranslate(filename);
        StringBuffer command = new StringBuffer("");
        StringBuffer hexStr = new StringBuffer("");

        List<String> hexVal = HexArray2Int2(asciiVal);
        for (String item : hexVal) {
            hexStr.append(item);
        }
        String comandLength = countLen(hexStr.toString());


        command.append(cmdType + comandLength + hexStr.toString());
        command.append(countCRC(command.toString()) + "00");
        Log.e("TAG", "handleClickToTranslate: " + command.toString());
        return command.toString();
    }

    private static String countLen(String str) {
        int dataLen = str.length() / 2;
        return dataLen > 15 ? Integer.toHexString(dataLen) : "0" + Integer.toHexString(dataLen);
    }

    private static String countCRC(String hexString) {
        List<String> hexAry = new ArrayList<>();
        int sum = 0;
        for (int i = 0; i < hexString.length(); i += 2) {
            sum += HexStringToInt(hexString.substring(i, i + 2));
        }

        return Integer.toHexString(sum % 256).toLowerCase();
    }

    /**
     * @param sampleRate      采样率 8000
     * @param channels        单声道 1
     * @param sampleBits      16
     * @param destinationPath 存入的 地址
     * @param bytes
     * @throws IOException
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static void convertPCMFileToWAVFile(int sampleRate, short channels, short sampleBits, String destinationPath, byte[] bytes) throws IOException {
        // 先删除目标文件
        File wavFile = new File(destinationPath);
        if (wavFile.exists()) {
            wavFile.delete();
        }
        WavHeader header = new WavHeader(bytes.length, sampleRate, channels, sampleBits);
        OutputStream outStream = new BufferedOutputStream(new FileOutputStream(wavFile));
        // 写入WAVFile 头部
        try {
            outStream.write(header.getHeader());
            outStream.write(bytes);
            Log.e("TAG", "convertPCMFileToWAVFile: 完成 " + HexUtil.parseByte2HexStr(header.getHeader()));
        } catch (IOException e) { // 写入头部失败
            throw e;
        } finally {
            try {
                outStream.close();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
        Log.i("PcmToWav", "makePCMFileToWAVFile  success!" + new SimpleDateFormat("yyyy-MM-dd hh:mm").format(new Date()));
    }

    /**
     * 获取 音频长度
     *
     * @param url
     * @return
     */
    public static Integer getDuration(String url) {
        try {
            //1.初始化midiaplayer
            MediaPlayer mediaPlayer = new MediaPlayer();
            //2.设置要播放的资源位置  path 可以是网络路径 也可以是本地路径
            mediaPlayer.setDataSource(url);
            mediaPlayer.prepare();
            Log.e("TAG", "onClick: getDuration" + mediaPlayer.getDuration());
            return mediaPlayer.getDuration();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static boolean getConnectedBtDevice() {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;//得到BluetoothAdapter的Class对象
        try {
            //得到连接状态的方法
            Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState", (Class[]) null);
            //打开权限
            method.setAccessible(true);
//            int state = (int) method.invoke(adapter, (Object[]) null);
//            if(state == BluetoothAdapter.STATE_CONNECTED){
            Log.i("BLUETOOTH", "BluetoothAdapter.STATE_CONNECTED");
            Set<BluetoothDevice> devices = adapter.getBondedDevices(); //集合里面包括已绑定的设备和已连接的设备
            Log.i("BLUETOOTH", "devices:" + devices.size());
            for (BluetoothDevice device : devices) {
                Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected", (Class[]) null);
                method.setAccessible(true);
                boolean isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
                if (isConnected) { //根据状态来区分是已连接的还是已绑定的，isConnected为true表示是已连接状态。
                    Log.i("BLUETOOTH-dh", "connected:" + device.getName());
                    //deviceList.add(device);
                    return true;
                }
//                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }
}
